In [1]:
import sdm as sdmlib
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont
import urllib, cStringIO
import random
from IPython.core.display import display, Image as IPythonImage
%matplotlib inline
In [2]:
width = 31
height = 32
noise_flip = True
In [3]:
def gen_img(letter='A'):
img = Image.new('RGBA', (width, height), (255, 255, 255))
font = ImageFont.truetype('Arial.ttf', 30)
draw = ImageDraw.Draw(img)
w, h = draw.textsize(letter, font=font)
top = (height-w)//2
left = (width-h)//2 if h <= 30 else 30-2-h
draw.text((top, left), letter, (0, 0, 0), font=font)
return img
In [4]:
def gen_noise_add(img, p=0.15, flip=False):
img2 = img.copy()
draw = ImageDraw.Draw(img2)
for py in xrange(height):
for px in xrange(width):
if random.random() < p:
if flip:
pixel = img.getpixel((px, py))
value = sum([int(x/255+0.5) for x in pixel[:3]])//3
assert value == 0 or value == 1
value = (1 - value)*255
draw.point((px, py), fill=(value, value, value))
else:
draw.point((px, py), fill=(0, 0, 0))
return img2
In [5]:
img = gen_img(letter='A');
img2 = gen_noise_add(img, p=0.05, flip=noise_flip)
plt.subplot(1, 2, 1)
plt.imshow(img)
plt.subplot(1, 2, 2)
plt.imshow(img2);
In [6]:
def to_bitstring(img):
v = []
bs = sdmlib.Bitstring.init_ones(1000)
for py in xrange(height):
for px in xrange(width):
pixel = img.getpixel((px, py))
value = sum([int(x/255+0.5) for x in pixel[:3]])//3
assert value == 0 or value == 1
idx = px+width*py
assert idx >= 0 and idx < 1000, 'Ops {} {} {}'.format(x, y, idx)
bs.set_bit(idx, value)
v.append(value)
v2 = [bs.get_bit(i) for i in xrange(height*width)]
assert v == v2
return bs
In [7]:
def to_img(bs):
img = Image.new('RGBA', (30, 30), (255, 255, 255))
draw = ImageDraw.Draw(img)
for py in xrange(height):
for px in xrange(width):
idx = px+width*py
assert idx >= 0 and idx < 1000, 'Ops {} {} {}'.format(x, y, idx)
x = 255*bs.get_bit(idx)
draw.point((px, py), fill=(x, x, x))
return img
In [8]:
bits = 1000
sample = 1000000
scanner_type = sdmlib.SDM_SCANNER_THREAD
In [9]:
address_space = sdmlib.AddressSpace.init_from_b64_file('sdm-letters.as')
In [10]:
counter = sdmlib.Counter.create_file('sdm-classification-3', bits, sample)
sdm = sdmlib.SDM(address_space, counter, 451, scanner_type)
In [11]:
def fill_memory(letter, label_bs, p=0.1, n=100):
cols = 15
rows = n//cols + 1
plt.figure(figsize=(20,10))
for i in xrange(n):
img = gen_img(letter=letter);
img2 = gen_noise_add(img, p=p, flip=noise_flip)
#display(img2)
plt.subplot(rows, cols, i+1)
plt.imshow(img2)
bs = to_bitstring(img2)
sdm.write(bs, label_bs)
plt.show()
In [12]:
def read(letter, n=6, p=0.2, radius=None):
img = gen_img(letter=letter);
img2 = gen_noise_add(img, p=p, flip=noise_flip)
plt.imshow(img2)
bs2 = to_bitstring(img2)
bs3 = sdm.read(bs2, radius=radius)
label = min(label_to_bs.items(), key=lambda v: bs3.distance_to(v[1]))
return label[0]
In [13]:
def iter_read(letter, n=10, p=0.2):
cols = 15
rows = n//cols + 1
plt.figure(figsize=(20,10))
wrong = 0
correct = 0
answers = []
for i in xrange(n):
plt.subplot(rows, cols, i+1)
y = read(x, p=p)
answers.append(y)
if x == y:
correct += 1
else:
wrong += 1
plt.show()
print '!! {} correct={:2d} wrong={:2d} answers={}'.format(x, correct, wrong, answers)
In [14]:
labels = list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
label_to_bs = {}
for x in labels:
label_to_bs[x] = sdmlib.Bitstring.init_random(1000)
In [15]:
for x in labels:
print 'Training for label {}...'.format(x)
fill_memory(x, label_to_bs[x])
In [16]:
for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789':
iter_read(x)
In [17]:
for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789':
iter_read(x, p=0.05)
In [18]:
for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789':
iter_read(x, p=0, n=1)
In [ ]: